#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
using ll=long long;
const int N=2010;
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};
ll dist[N*N];
ll w[N*N];
int vis[N*N];
int n,m;
int get_idx(int x,int y)
{
	return (x-1)*m+y;
}
struct cmp{
	bool operator()(const pair<pair<int,int>,ll> &p1,const pair<pair<int,int>,ll> &p2)
	{
		return p1.second>p2.second;
	}
};
void dijkstra()
{
	priority_queue<pair<pair<int,int>,ll>,vector<pair<pair<int,int>,ll>>,cmp> q;
	q.push({{1,1},0});
	memset(dist,0x3f3f3f3f,sizeof(dist));
	dist[1]=0;
	
	
	
	while(q.size())
	{
		int x=q.top().first.first;
		int y=q.top().first.second;
		q.pop();
		int uIdx=get_idx(x,y);
		if(vis[uIdx])
			continue;
		vis[uIdx]=1;
		for(int i=0;i<4;i++)
		{
			int nx=x+dx[i];
			int ny=y+dy[i];
//			cout<<nx<<' '<<ny<<endl;
			if(nx<=0 || nx>n || ny<=0 || ny>m)
			{
				continue;
			}
			int uIdx=get_idx(x,y);
			int toIdx=get_idx(nx,ny);
			
			if(dist[toIdx]>dist[uIdx]+w[uIdx])
			{
				dist[toIdx]=dist[uIdx]+w[uIdx];
				q.push({{nx,ny},dist[toIdx]});
				
			}
		}
	}
}
int main()
{
	
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			int idx=get_idx(i,j);
			
			cin>>w[idx];
			
		}
	}
//	for(int i=1;i<=n;i++)
//	{
//		for(int j=1;j<=m;j++)
//		{
//			cout<<get_idx(i,j)<<endl;
//		}
//	}
	dijkstra();
	ll ret=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			int idx=get_idx(i,j);
			
			ret=max(ret,dist[idx]+w[idx]);
		}
	}
	cout<<ret<<endl;
	return 0;
}
//2 3
//1 2 3
//4 5 6
